package server.communication.listeners;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import server.Server;
import server.threads.ServerCommunicator;
import message.InsertDataRequestMessage;
import message.InsertDataResponseMessage;
import message.Message;
import message.ServerMessageWrapper;
import message.UpdateDataRequestMessage;
import communication.MessageListener;
import communication.MessageReceivedEvent;

public class InsertDataListener implements MessageListener
{
	private final ServerCommunicator communicator;
	private final Server server;
	
	public InsertDataListener(ServerCommunicator communicator, Server server)
	{
		this.communicator = communicator;
		this.server = server;
	}
	private boolean insertData(InsertDataRequestMessage message, boolean sentByServer)
	{
		boolean success = false;
		int id = message.getId();
		java.sql.Connection dbConnection = server.getDatabaseConnection();
		
		//TODO abstract this if-else block into methods
		
		if (id > 0)
		{
			try
			{
				Statement statement = dbConnection.createStatement();
				statement.execute("UPDATE capstone.users SET userId = userId+1 WHERE creationTime>" + message.getDateCreated() + " ORDER BY userId DESC");
				
				statement = dbConnection.createStatement();
				statement.execute("SELECT userId FROM capstone.users WHERE creationTime>" + message.getDateCreated() + " LIMIT 1");
				
				ResultSet results = statement.getResultSet();
				
				results.first();
				
				id = results.getInt(1);
				
				statement.execute("INSERT INTO users (userId, username, password) VALUES ('" + id + "', '" + message.getUsername() + "', '" + message.getPassword() + "')");
				
				success = true;
				
				UpdateDataRequestMessage updateMessage = new UpdateDataRequestMessage();
				
				updateMessage.setId(id);
				updateMessage.setUsername(message.getUsername());
				updateMessage.setPassword(message.getPassword());

				communicator.broadcastToServers(updateMessage);
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			if (dbConnection != null)
			{
				try
				{
					Statement statement = dbConnection.createStatement();
					statement.execute("INSERT INTO users (username, password) VALUES ('" + message.getUsername() + "', '" + message.getPassword() + "')");
				
					success = true;
					
					id = getId(message.getUsername());
					
					System.out.println("ID:" + id);
					
					InsertDataRequestMessage broadcastMessage = new InsertDataRequestMessage();
					
					broadcastMessage.setUsername(message.getUsername());
					broadcastMessage.setPassword(message.getPassword());
					broadcastMessage.setId(id);
					broadcastMessage.setDateCreated(getCreationTime(message.getPassword()));
					
					if (!sentByServer)
						communicator.broadcastToServers(broadcastMessage);
				}
				catch (SQLException e) { e.printStackTrace(); }
			}
		}
		
		try
		{
			if (dbConnection != null)
				dbConnection.close();
		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}
		
		return success;
	}
	private long getCreationTime(String username)
	{
		java.sql.Connection dbConnection = server.getDatabaseConnection();
		
		if (dbConnection != null)
		{
			try
			{
				Statement statement = dbConnection.createStatement();
				ResultSet results;
				
				statement.execute("SELECT userId FROM `users` WHERE username='" + username + "'");
				
				results = statement.getResultSet();
				
				results.first();
				
				return results.getLong("creationTime");
			}
			catch (SQLException e) {}
			finally
			{
				try
				{
					dbConnection.close();
				}
				catch (SQLException e) {}
			}
		}
		
		return -1;
	}
	private int getId(String username)
	{
		java.sql.Connection dbConnection = server.getDatabaseConnection();
		
		if (dbConnection != null)
		{
			try
			{
				Statement statement = dbConnection.createStatement();
				ResultSet results;
				
				statement.execute("SELECT userId FROM `users` WHERE username='" + username + "'");
				
				results = statement.getResultSet();
				
				results.first();
				
				return results.getInt("userId");
			}
			catch (SQLException e) {}
			
			try
			{
				dbConnection.close();
			}
			catch (SQLException e) {}
		}
		
		return -1;
	}
	@Override
	public void messageRecieved(MessageReceivedEvent e)
	{
		ServerMessageWrapper message = ((ServerMessageWrapper) e.getMessage());
		InsertDataRequestMessage innerMessage = (InsertDataRequestMessage) message.internalMessage;
		InsertDataResponseMessage response = new InsertDataResponseMessage();
		boolean success = insertData(innerMessage, message.sentByServer);
		
		response.setSuccess(success);
		
		if (success)
			server.dataSynchronized();
		
		communicator.sendMessage(message.connectionId, response);
		
		server.dataSynchronized();
	}

	@Override
	public boolean acceptsMessage(Message message)
	{
		if (message.getClass().equals(ServerMessageWrapper.class))
			message = ((ServerMessageWrapper) message).internalMessage;
		
		return message.getClass().equals(InsertDataRequestMessage.class);
	}
}
